use Action;

package SpawnCreatureAction;
@ISA = qw/Action/;

our @DEPENDS_ON = qw/EntityManager MapManager LogManager InputManager/;

### Spawns an entity on an unoccupied tile
###
### Given parameters must be:
###
### ---- ENTITY: A reference to the entity that is the source of the spawning; optionally, can be ommitedb
###              if WELL_KNOWN_ENTITY is specified
###
### ---- WELL_KNOWN_ENTITY: The name of a well known entity registered
###                         at the EntityManager. If present, ENTITY takes
###                         precedence and this is ignored
###
### ---- MAP: A reference to the map to be placed on; if none is given,
###           the default map will be taken from the MapManager
###        
### ---- DIRECTION: UP | DOWN | LEFT | RIGHT
###
### ---------------------------------------------------------
### =========================================================


sub perform{
    my $self = shift;
    my $lm = $self->{LogManager};

    my $ok = 1;
    $ok = $ok && $self->validateActingEntity;
    $ok = $ok && $self->validateMap;
    
    if(!$ok){
	$lm->log((ref $self).": ERROR: Parameter validation failed");
	return ActionResult->new("SILENT_IGNORE", "Parameter validation errors");
    }


    unless($self->validateDirection){
	$self->{InputManager}->pushBindings("MENU_BASIC");
	my $validCommands = ["Up", "Down", "Left", "Right", "Cancel"];
	$command = $self->{InputManager}->waitForKeyCommandFromList($validCommands);
	$self->{InputManager}->popBindings();

	if($command eq "Cancel"){
	    return ActionResult->new("FAILURE", "Cancelled");
	}
	$self->params->{DIRECTION} = $command;
    }

    my ($entity, $map, $direction) = ($self->params->{ENTITY},
				      $self->params->{MAP},
				      $self->params->{DIRECTION});


    my @pos = @{$entity->pos($map)};
    $lm->log("POS(".$pos[0].", ".$pos[1].")");
    $ok = ActionHelper::getNewPos(\@pos, $direction, $map, $lm);
    $lm->log("POS(".$pos[0].", ".$pos[1].")");
    return ActionResult->new("SILENT_IGNORE", "Target out of bounds!") unless($ok);
    
    my $cell = $map->tiles->[$pos[0]][$pos[1]];

    my $aux = $cell->contents->category("CREATURE");
    foreach(@{$aux}){
	$lm->log($_->type);
    }


    my $occupied = scalar(@{$cell->contents->find({PASSABLE=>0}, ["CONSTRUCTION"])});
    $occupied = $occupied || scalar(@{$cell->contents->category("CREATURE")});

    return ActionResult->new("FAILURE","Destination is occupied!") if($occupied);


    my $spawnling = Spawnling->spawn;

    $spawnling->place($map, $pos[0], $pos[1], "CREATURE");
    return ActionResult->new("SUCCESS", "Spawned!");
}


## Calculates the new position,
## based on the direction, the 
## old position, the map's height
## and width
##
## Parameters:
##    oldPosition : Array reference [X, Y]
##    direction : scalar
##    height, width : scalars
sub getNewPos{
    my $self = shift;
    my $oldPos = shift;
    my $dir = shift;
    my ($w, $h) = (shift, shift);

    my $newPos = [$oldPos->[0], $oldPos->[1]];
    if($dir eq "UP"){
	$newPos->[1] -= 1 unless($oldPos->[1] == 0);
    }
    if($dir eq "DOWN"){
	$newPos->[1] += 1 unless($oldPos->[1] == $h-1);
    }
    if($dir eq "LEFT"){
	$newPos->[0] -= 1 unless($oldPos->[0] == 0);
    }
    if($dir eq "RIGHT"){
	$newPos->[0] += 1 unless($oldPos->[0] == $w-1);
    }

#    print "(".$oldPos->[0].", ".$oldPos->[1].") -> (".$newPos->[0].", ".$newPos->[1].")\n";
 #   print "=======================\n";

    return $newPos;
}
